package guiMVC;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import reader.ResultReader;
import reader.SolutionReader;
import value_object.InstanceVO;
import value_object.ResultVO;
import value_object.SolutionVO;

public class Model {
	private Boolean viewInDetail;
	private InstanceVO instance;
	private SolutionVO solution;
	private ResultVO result;
	
	private List<IView> viewList; //list of views - observers
	
	private static Model model;
	
	private Model() {
		viewInDetail = new Boolean(false);
		instance = new InstanceVO();
		solution = new SolutionVO();
		result = new ResultVO();
		viewList = new ArrayList<IView>();
	}
	
	public static synchronized Model getModel() {
		if (model == null)
			model = new Model();
		return model;
	}
	
	//register observer
	public void addView(IView view) {
		if (!viewList.contains(view)) {
			viewList.add(view);
		}
	}
	
	//remove observer
	public void removeView(IView view) {
		viewList.remove(view);
	}
	
	//update model
	public void updateModel(Object data) {
		if (data instanceof InstanceVO) {
			instance = (InstanceVO) data;
			
		}
		else if (data instanceof SolutionVO) {
			solution = (SolutionVO) data;
			
			//write solution to file
			SolutionReader solutionReader = new SolutionReader();
			try {
				solutionReader.writeSolution(solution);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		else if (data instanceof ResultVO) {
			result = (ResultVO) data;
			
			//write result to file
			ResultReader resultReader = new ResultReader();
			try {
				resultReader.writeResult(result);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		else if (data instanceof Boolean) {
			viewInDetail = (Boolean) data;
		}
		
		//update Views each time Model get modified..
		updateViews();
	}	
	
	public InstanceVO getInstance() {
		return instance;
	}
	
	public SolutionVO getSolution() {
		return solution;
	}

	public void setSolution(SolutionVO solution) {
		this.solution = solution;
	}

	public ResultVO getResult() {
		return result;
	}

	public void setResult(ResultVO result) {
		this.result = result;
	}

	public void setInstance(InstanceVO instance) {
		this.instance = instance;
	}
	
	/**
	 * This method is used for updating Views each time Model get modified..
	 */
	private void updateViews() {
		Iterator<IView> notifiedViews = viewList.iterator();
		while (notifiedViews.hasNext()) {
			IView iView = (IView) notifiedViews.next();
			if (viewInDetail)
				iView.updateView(instance.toString(), solution.toString(), result.toString());
			else
				iView.updateView(instance.toSimpleString(), solution.toSimpleString(), result.toSimpleString());
		}
	}
}
